import * as Config from 'config'
import { Menu } from '@/entities/menu.entity'
import { Permission } from '@/entities/permission.entity'
import { Role } from '@/entities/role.entity'
import { TMenuStatus } from '@/enum/commom.emun'

export type TMenu = {
  id: string
  parentId: string
  menuName: string
  constant: boolean
  roles?: Role[]
  children?: TMenu[]
}
export type TFormatMenu = {
  id: string
  pId: string
  label: string
  children?: TFormatMenu[]
}

export type TBaseRoute = {
  routeName: string
  path: string
  routePath: string
  component: string
  props?: boolean
  children?: TUserRoute[]
}

export type TMeta = {
  menuType?: string
  title?: string
  i18nKey: string
  constant: boolean
  hideInMenu: boolean
  icon: string
  order?: number
  activeMenu: string
  keepAlive: boolean
  multiTab: boolean
  roles?: string[]
}

export type TRoute = {
  id: string
  menuName: string
  status?: TMenuStatus
  roles?: Role[]
  permissions?: Permission[]
  children?: TRoute[]
} & Omit<TBaseRoute, 'children' | 'path'> &
  Omit<TMeta, 'roles'>

export type TPermission = {
  id: string
  desc: string
  code: string
  i18nKey?: string
  children?: TPermission[]
}

export type TUserRoute = Omit<TBaseRoute, 'routeName' | 'routePath'> & {
  meta: TMeta
}
export const formatMenu = (menu: TMenu[], roleCodes: string[]) => {
  const result: TFormatMenu[] = menu
    .filter(
      (item) =>
        !item.constant &&
        (roleCodes.includes(Config.get('role').superAdminCode) ||
          roleCodes.some((codeItem) =>
            item.roles.some((roleItem) => roleItem.roleCode === codeItem)
          ))
    )
    .map((item) => {
      const { id, parentId: pId, menuName: label } = item
      const tempResult = { id, pId, label }
      if (item.children?.length) {
        tempResult['children'] = formatMenu(item.children, roleCodes)
      }
      return tempResult
    })
  return result
}

export const sortMenuByOrder = (menu: Menu[]): Menu[] => {
  menu.sort((a, b) => a.order - b.order)
  const result: Menu[] = menu.map((item) => {
    if (item.children?.length) {
      item['children'] = sortMenuByOrder(item.children)
    }
    return item
  })
  return result
}

const isChildrenHasPermission = (data: TRoute) => {
  let flag = data.permissions.length ? true : false
  if (data.children && !flag) {
    for (let i = 0; i < data.children.length; i = i + 1) {
      const childrenData = data.children[i]
      if (childrenData.permissions) {
        flag = true
        break
      } else {
        isChildrenHasPermission(childrenData)
      }
    }
  }

  return flag
}

export const generatePermissions = (menu: TRoute[]) => {
  const result: TPermission[] = menu
    .filter((item) => !item.constant && isChildrenHasPermission(item))
    .map((item) => {
      const { routeName, routePath, i18nKey, permissions } = item
      const tempResult = {
        id: routeName,
        desc: routeName,
        i18nKey,
        code: routePath,
        children: permissions.map((permissionItem) => {
          const { id, permissionDesc, permissionCode } = permissionItem
          return {
            id,
            desc: permissionDesc,
            code: permissionCode,
          }
        }),
      }
      if (item.children?.length) {
        tempResult['children'] = generatePermissions(item.children)
      }
      return tempResult
    })
  return result
}

export const generateConstantRoutes = (menu: TRoute[]) => {
  const result: TUserRoute[] = menu
    .filter((item) => item.menuType !== '1' && item.constant)
    .map((item) => {
      const {
        routeName,
        routePath,
        component,
        props,
        menuName,
        i18nKey,
        constant,
        hideInMenu,
        icon,
        activeMenu,
        keepAlive,
        multiTab,
      } = item
      const tempResult = {
        name: routeName,
        path: routePath,
        component,
        props,
        meta: {
          title: menuName,
          i18nKey,
          constant,
          hideInMenu,
          icon,
          activeMenu,
          keepAlive,
          multiTab,
        },
      }
      return tempResult
    })
  return result
}

export const generateUserRoutes = (menu: TRoute[], roleCodes: string[]) => {
  const result: TUserRoute[] = menu
    .filter(
      (item) =>
        roleCodes.includes(Config.get('role').superAdminCode) ||
        (!item.constant &&
          item.status === TMenuStatus.enable &&
          roleCodes.some((codeItem) =>
            item.roles.some((roleItem) => roleItem.roleCode === codeItem)
          ))
    )
    .map((item) => {
      const {
        routeName,
        routePath,
        component,
        props,
        menuName,
        i18nKey,
        constant,
        hideInMenu,
        icon,
        order,
        activeMenu,
        keepAlive,
        multiTab,
        roles,
      } = item
      const hasUserRoleCodes = roles?.map((role) => role.roleCode) || []
      const tempResult = {
        name: routeName,
        path: routePath,
        component,
        props,
        meta: {
          title: menuName,
          i18nKey,
          constant,
          hideInMenu,
          icon,
          order,
          activeMenu,
          keepAlive,
          multiTab,
          roles: [...hasUserRoleCodes, Config.get('role').superAdminCode],
        },
      }
      if (item.children?.length) {
        tempResult['children'] = generateUserRoutes(item.children, roleCodes)
      }
      return tempResult
    })
  return result
}

export type TMenuWithButtom = Omit<Menu, 'permissions' | 'children'> & {
  children?: TMenuWithButtom[]
  buttons: { code: string; desc: string }[]
}
export const formatMenuWithButtons = (menu: Menu[]): TMenuWithButtom[] => {
  const result: TMenuWithButtom[] = menu.map((item) => {
    const { permissions = [], ...rest } = item
    const tempResult: TMenuWithButtom = {
      ...rest,
      children: [],
      buttons: [],
    }

    if (permissions?.length) {
      tempResult.buttons = permissions.map((permissionItem) => ({
        code: permissionItem.permissionCode,
        desc: permissionItem.permissionDesc,
      }))
    }
    if (item.children?.length) {
      tempResult['children'] = formatMenuWithButtons(item.children)
    }
    return tempResult
  })
  return result
}
